"""
@Time ： 2025/8/28 17:25
@Auth ： zh
@File ：chess.py
中国象棋游戏实现
"""
import copy

class ChessPiece:
    """棋子基类"""
    def __init__(self, name, color, position):
        self.name = name  # 棋子名称
        self.color = color  # 颜色：红/黑
        self.position = position  # 位置 (row, col)
        self.has_moved = False  # 是否已经移动过（用于马走日、象走田等特殊规则）
    
    def __str__(self):
        # 红棋用中文，黑棋用拼音首字母
        if self.color == 'red':
            return self.name
        else:
            # 黑棋棋子名称的拼音首字母
            names_map = {'车': 'R', '马': 'N', '象': 'E', '士': 'A', '将': 'K', '炮': 'C', '兵': 'P'}
            return names_map.get(self.name, self.name)
    
    def is_valid_move(self, board, to_row, to_col):
        """检查移动是否有效"""
        # 子类需要实现具体的移动规则
        pass

class Rook(ChessPiece):
    """车"""
    def __init__(self, color, position):
        super().__init__('车', color, position)
    
    def is_valid_move(self, board, to_row, to_col):
        from_row, from_col = self.position
        
        # 车只能直线移动
        if from_row != to_row and from_col != to_col:
            return False
        
        # 检查路径上是否有棋子阻挡
        if from_row == to_row:
            # 水平移动
            step = 1 if to_col > from_col else -1
            for col in range(from_col + step, to_col, step):
                if board[from_row][col] is not None:
                    return False
        else:
            # 垂直移动
            step = 1 if to_row > from_row else -1
            for row in range(from_row + step, to_row, step):
                if board[row][from_col] is not None:
                    return False
        
        # 检查目标位置是否有己方棋子
        target_piece = board[to_row][to_col]
        if target_piece is not None and target_piece.color == self.color:
            return False
        
        return True

class Horse(ChessPiece):
    """马"""
    def __init__(self, color, position):
        super().__init__('马', color, position)
    
    def is_valid_move(self, board, to_row, to_col):
        from_row, from_col = self.position
        
        # 马走日字
        row_diff = abs(to_row - from_row)
        col_diff = abs(to_col - from_col)
        if not ((row_diff == 2 and col_diff == 1) or (row_diff == 1 and col_diff == 2)):
            return False
        
        # 检查马腿是否被绊住
        if row_diff == 2:
            # 上下移动两格
            leg_row = from_row + 1 if to_row > from_row else from_row - 1
            if board[leg_row][from_col] is not None:
                return False
        else:
            # 左右移动两格
            leg_col = from_col + 1 if to_col > from_col else from_col - 1
            if board[from_row][leg_col] is not None:
                return False
        
        # 检查目标位置是否有己方棋子
        target_piece = board[to_row][to_col]
        if target_piece is not None and target_piece.color == self.color:
            return False
        
        return True

class Elephant(ChessPiece):
    """象（相）"""
    def __init__(self, color, position):
        name = '象' if color == 'black' else '相'
        super().__init__(name, color, position)
    
    def is_valid_move(self, board, to_row, to_col):
        from_row, from_col = self.position
        
        # 象走田字
        row_diff = abs(to_row - from_row)
        col_diff = abs(to_col - from_col)
        if row_diff != 2 or col_diff != 2:
            return False
        
        # 检查象眼是否被塞住
        eye_row = (from_row + to_row) // 2
        eye_col = (from_col + to_col) // 2
        if board[eye_row][eye_col] is not None:
            return False
        
        # 象不能过河
        if self.color == 'red' and to_row > 4:
            return False
        if self.color == 'black' and to_row < 5:
            return False
        
        # 检查目标位置是否有己方棋子
        target_piece = board[to_row][to_col]
        if target_piece is not None and target_piece.color == self.color:
            return False
        
        return True

class Advisor(ChessPiece):
    """士（仕）"""
    def __init__(self, color, position):
        name = '士' if color == 'black' else '仕'
        super().__init__(name, color, position)
    
    def is_valid_move(self, board, to_row, to_col):
        from_row, from_col = self.position
        
        # 士走斜线，且只能在九宫格内
        row_diff = abs(to_row - from_row)
        col_diff = abs(to_col - from_col)
        if row_diff != 1 or col_diff != 1:
            return False
        
        # 检查是否在九宫格内
        if self.color == 'red':
            if not (7 <= to_row <= 9 and 3 <= to_col <= 5):
                return False
        else:
            if not (0 <= to_row <= 2 and 3 <= to_col <= 5):
                return False
        
        # 检查目标位置是否有己方棋子
        target_piece = board[to_row][to_col]
        if target_piece is not None and target_piece.color == self.color:
            return False
        
        return True

class General(ChessPiece):
    """将（帅）"""
    def __init__(self, color, position):
        name = '将' if color == 'black' else '帅'
        super().__init__(name, color, position)
    
    def is_valid_move(self, board, to_row, to_col):
        from_row, from_col = self.position
        
        # 将只能在九宫格内上下左右移动一格
        row_diff = abs(to_row - from_row)
        col_diff = abs(to_col - from_col)
        if not ((row_diff == 1 and col_diff == 0) or (row_diff == 0 and col_diff == 1)):
            return False
        
        # 检查是否在九宫格内
        if self.color == 'red':
            if not (7 <= to_row <= 9 and 3 <= to_col <= 5):
                return False
        else:
            if not (0 <= to_row <= 2 and 3 <= to_col <= 5):
                return False
        
        # 检查目标位置是否有己方棋子
        target_piece = board[to_row][to_col]
        if target_piece is not None and target_piece.color == self.color:
            return False
        
        return True
    
    def check_face_to_face(self, board, to_row, to_col):
        """检查将帅是否对面"""
        # 这里简化处理，实际游戏中需要更复杂的将帅对面判断
        pass

class Cannon(ChessPiece):
    """炮"""
    def __init__(self, color, position):
        super().__init__('炮', color, position)
    
    def is_valid_move(self, board, to_row, to_col):
        from_row, from_col = self.position
        
        # 炮只能直线移动
        if from_row != to_row and from_col != to_col:
            return False
        
        # 计算炮架数量
        cannon_mounts = 0
        if from_row == to_row:
            # 水平移动
            step = 1 if to_col > from_col else -1
            for col in range(from_col + step, to_col, step):
                if board[from_row][col] is not None:
                    cannon_mounts += 1
        else:
            # 垂直移动
            step = 1 if to_row > from_row else -1
            for row in range(from_row + step, to_row, step):
                if board[row][from_col] is not None:
                    cannon_mounts += 1
        
        # 炮吃子需要一个炮架，移动不需要炮架
        target_piece = board[to_row][to_col]
        if target_piece is None:
            # 移动时不能有炮架
            if cannon_mounts != 0:
                return False
        else:
            # 吃子时需要一个炮架
            if cannon_mounts != 1 or target_piece.color == self.color:
                return False
        
        return True

class Soldier(ChessPiece):
    """兵（卒）"""
    def __init__(self, color, position):
        name = '卒' if color == 'black' else '兵'
        super().__init__(name, color, position)
    
    def is_valid_move(self, board, to_row, to_col):
        from_row, from_col = self.position
        
        # 兵只能前进或过河后横向移动一格
        row_diff = to_row - from_row
        col_diff = abs(to_col - from_col)
        
        # 红方和黑方的前进方向相反
        if self.color == 'red':
            # 红方兵向上（行号减小的方向）移动
            if row_diff >= 0:
                return False  # 不能后退
        else:
            # 黑方兵向下（行号增大的方向）移动
            if row_diff <= 0:
                return False  # 不能后退
        
        # 只能移动一格
        if abs(row_diff) > 1 or col_diff > 1:
            return False
        
        # 只有过河后才能横向移动
        if col_diff == 1:
            if self.color == 'red' and from_row > 4:
                return False  # 红兵未过河
            if self.color == 'black' and from_row < 5:
                return False  # 黑卒未过河
        
        # 检查目标位置是否有己方棋子
        target_piece = board[to_row][to_col]
        if target_piece is not None and target_piece.color == self.color:
            return False
        
        return True

class ChessBoard:
    """棋盘类"""
    def __init__(self):
        # 创建10行9列的棋盘
        self.board = [[None for _ in range(9)] for _ in range(10)]
        self.current_turn = 'red'  # 红方先行
        self.history = []  # 记录历史走法
        self.setup_board()
    
    def setup_board(self):
        """初始化棋盘，放置所有棋子"""
        # 放置黑方棋子
        self.board[0][0] = Rook('black', (0, 0))
        self.board[0][1] = Horse('black', (0, 1))
        self.board[0][2] = Elephant('black', (0, 2))
        self.board[0][3] = Advisor('black', (0, 3))
        self.board[0][4] = General('black', (0, 4))
        self.board[0][5] = Advisor('black', (0, 5))
        self.board[0][6] = Elephant('black', (0, 6))
        self.board[0][7] = Horse('black', (0, 7))
        self.board[0][8] = Rook('black', (0, 8))
        self.board[2][1] = Cannon('black', (2, 1))
        self.board[2][7] = Cannon('black', (2, 7))
        self.board[3][0] = Soldier('black', (3, 0))
        self.board[3][2] = Soldier('black', (3, 2))
        self.board[3][4] = Soldier('black', (3, 4))
        self.board[3][6] = Soldier('black', (3, 6))
        self.board[3][8] = Soldier('black', (3, 8))
        
        # 放置红方棋子
        self.board[9][0] = Rook('red', (9, 0))
        self.board[9][1] = Horse('red', (9, 1))
        self.board[9][2] = Elephant('red', (9, 2))
        self.board[9][3] = Advisor('red', (9, 3))
        self.board[9][4] = General('red', (9, 4))
        self.board[9][5] = Advisor('red', (9, 5))
        self.board[9][6] = Elephant('red', (9, 6))
        self.board[9][7] = Horse('red', (9, 7))
        self.board[9][8] = Rook('red', (9, 8))
        self.board[7][1] = Cannon('red', (7, 1))
        self.board[7][7] = Cannon('red', (7, 7))
        self.board[6][0] = Soldier('red', (6, 0))
        self.board[6][2] = Soldier('red', (6, 2))
        self.board[6][4] = Soldier('red', (6, 4))
        self.board[6][6] = Soldier('red', (6, 6))
        self.board[6][8] = Soldier('red', (6, 8))
    
    def display(self):
        """显示棋盘"""
        print('  0 1 2 3 4 5 6 7 8')
        for i in range(10):
            print(f'{i} ', end='')
            for j in range(9):
                piece = self.board[i][j]
                if piece is None:
                    # 打印棋盘格点
                    if (i == 4 and 0 <= j <= 8) or (i == 5 and 0 <= j <= 8):
                        print('-', end=' ')
                    elif (i == 2 or i == 7) and (j == 1 or j == 7):
                        print('●', end=' ')
                    elif (i >= 0 and i <= 2) or (i >= 7 and i <= 9):
                        if (j >= 3 and j <= 5):
                            print('┼', end=' ')
                        else:
                            print('.', end=' ')
                    else:
                        print('.', end=' ')
                else:
                    print(piece, end=' ')
            print()
    
    def move_piece(self, from_row, from_col, to_row, to_col):
        """移动棋子"""
        # 检查起始位置是否有棋子
        piece = self.board[from_row][from_col]
        if piece is None:
            print("起始位置没有棋子！")
            return False
        
        # 检查是否是当前回合的玩家
        if piece.color != self.current_turn:
            print(f"现在是{self.current_turn}方回合！")
            return False
        
        # 检查移动是否有效
        if not piece.is_valid_move(self.board, to_row, to_col):
            print("移动无效！")
            return False
        
        # 保存移动前的状态用于悔棋
        self.history.append(copy.deepcopy(self.board))
        
        # 移动棋子
        captured_piece = self.board[to_row][to_col]
        self.board[to_row][to_col] = piece
        self.board[from_row][from_col] = None
        piece.position = (to_row, to_col)
        piece.has_moved = True
        
        # 检查将帅对面的情况（简化处理）
        if isinstance(piece, General) and captured_piece is not None and isinstance(captured_piece, General):
            # 这里应该有将帅对面的逻辑，但在移动规则中已经处理了
            pass
        
        # 切换回合
        self.current_turn = 'black' if self.current_turn == 'red' else 'red'
        
        return True
    
    def check_win(self):
        """检查是否有一方获胜"""
        red_king_exists = False
        black_king_exists = False
        
        for row in self.board:
            for piece in row:
                if piece is not None:
                    if piece.color == 'red' and isinstance(piece, General):
                        red_king_exists = True
                    elif piece.color == 'black' and isinstance(piece, General):
                        black_king_exists = True
        
        if not red_king_exists:
            return 'black'
        if not black_king_exists:
            return 'red'
        
        return None  # 没有人获胜

class ChessGame:
    """象棋游戏类"""
    def __init__(self):
        self.board = ChessBoard()
    
    def start(self):
        """开始游戏"""
        print("中国象棋游戏开始！")
        print("输入格式：from_row from_col to_row to_col")
        print("例如：9 0 8 0 表示红方车从(9,0)移动到(8,0)")
        print("输入 'exit' 退出游戏，输入 'undo' 悔棋")
        
        while True:
            self.board.display()
            
            # 检查是否有人获胜
            winner = self.board.check_win()
            if winner:
                print(f"{winner}方获胜！")
                break
            
            # 获取用户输入
            try:
                user_input = input(f"请{self.board.current_turn}方输入走法：")
                if user_input.lower() == 'exit':
                    print("游戏退出！")
                    break
                elif user_input.lower() == 'undo':
                    if self.board.history:
                        self.board.board = self.board.history.pop()
                        self.board.current_turn = 'black' if self.board.current_turn == 'red' else 'red'
                        print("已悔棋！")
                    else:
                        print("没有可悔的棋！")
                    continue
                
                # 解析输入
                move = list(map(int, user_input.split()))
                if len(move) != 4:
                    print("输入格式错误！请输入4个数字：from_row from_col to_row to_col")
                    continue
                
                from_row, from_col, to_row, to_col = move
                # 检查坐标是否在棋盘范围内
                if not (0 <= from_row < 10 and 0 <= from_col < 9 and 0 <= to_row < 10 and 0 <= to_col < 9):
                    print("坐标超出棋盘范围！")
                    continue
                
                # 移动棋子
                if not self.board.move_piece(from_row, from_col, to_row, to_col):
                    print("移动失败，请重试！")
                    continue
                
            except ValueError:
                print("输入格式错误！请输入数字或命令。")
                continue

if __name__ == "__main__":
    game = ChessGame()
    game.start()
